////////////////////////////////////////////////////////////////////
// File:	DecalManager.h
// Purpose: Manages all decals in game and uses a ring buffer to reuse
//			any decals so that we don't lag the game out because of
//			too many decals in game. You can create decals on the fly,
//			but remember decals will be reused and you cannot exceed
//			the capacity defined "MAX_DECALS."
// Author:	Jay Baird
////////////////////////////////////////////////////////////////////

#ifndef DECALMANAGER_H
#define DECALMANAGER_H

#ifndef MAX_DECALS
#define MAX_DECALS 512
#endif

#include "..\..\src\Util\Collision.h"
#include "..\..\src\Game Objects\Decal.h"

class DecalManager
{
private:
	typedef std::vector<Decal>::iterator DecalIter;
	typedef std::vector<Decal>::const_iterator DecalIterConst;

	unsigned m_numDecalsUsed;
	unsigned m_currentDecal;

	std::vector<BaseObject*> m_targets;
	std::vector<Decal> m_decals;	// Ring buffer, not accessable by the public
	std::vector<BaseObject*> m_currentDecals;
	std::vector<IRenderable*> m_renderables;

	static DecalManager m_instance;

	void AddTarget(Decal* pTarget);
	void RemoveTarget(Decal* pTarget);

	DecalManager();
	DecalManager(const DecalManager&);
	~DecalManager() { Shutdown(); }
	DecalManager& operator=(const DecalManager&);

public:
	static DecalManager* GetInstance() { return &m_instance; }

	// Resets all decals in the manager and reinits them
	// Ins: None
	// Outs: None
	// Return: None
	void Initialize();

	// Destructs all decals in the manager and resets the ring buffer counter
	// Ins: None
	// Outs: None
	// Return: None
	void Shutdown();

	// Updates all decals in the manager and calls appropriate functions
	// Ins: (fTimeStep): delta time
	// Outs: None
	// Return: None
	void UpdateDecals(const float fTimeStep);

	// Renders all decals in the manager or upto the current ring buffer counter
	// Ins: None
	// Outs: None
	// Return: None
	void RenderDecals() const;

	// Creates a decal on the fly according to whatever texture file and attaches itself to an object
	// Ins: (pTarget): target to attach the decal to
	//		(textureFile): the quad effect (decal) to put on the target object
	//		(center): position for the decal to be placed
	//		(planeType): plane to place the decal on
	//		(width): width of decal
	//		(height): height of decal
	//		(paintType): type of paint/color the decal is
	// Outs: None
	// Return: None
	void CreateDecal(BaseObject* pTarget, const char* textureFile, const vec3& center,
					 Collision::PlaneType planeType, float width, float height, PaintType paintType);

	unsigned GetDecalCount() const { return m_numDecalsUsed; }

	const std::vector<BaseObject*>& GetDecals() const { return m_currentDecals; }
	const std::vector<IRenderable*>& GetRenderableDecals() const { return m_renderables; }
	const std::vector<BaseObject*>& GetTargets() const { return m_targets; }
};

#endif